package com.hwtx.form.util;

import lombok.extern.slf4j.Slf4j;

import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.Collection;
import java.util.Date;
import java.util.Map;
import java.util.Random;

@Slf4j
public class BasicUtil {

    /**
     * 是否为空或""或"null"(大写字母"NULL"不算空) 集合对象检查是否为空或集合中是否有对象
     *
     * @param obj       obj
     * @param recursion recursion
     *                  是否递归查检集合对象
     * @return boolean
     */
    @SuppressWarnings("rawtypes")
    public static boolean isEmpty(boolean recursion, Object obj) {
        if (null == obj) {
            return true;
        }
        if (obj instanceof Collection collection && recursion) {
            if (collection.isEmpty()) {
                return true;
            }
            for (Object item : collection) {
                if (!isEmpty(recursion, item)) {
                    return false;
                }
            }
        } else if (obj.getClass().isArray()) {
            if (obj instanceof int[]) {
                return ((int[]) obj).length <= 0;
            } else if (obj instanceof double[]) {
                return ((double[]) obj).length <= 0;
            } else if (obj instanceof float[]) {
                return ((float[]) obj).length <= 0;
            } else if (obj instanceof short[]) {
                return ((short[]) obj).length <= 0;
            } else if (obj instanceof byte[]) {
                return ((byte[]) obj).length <= 0;
            } else if (obj instanceof boolean[]) {
                return ((boolean[]) obj).length <= 0;
            } else {
                Object[] array = (Object[]) obj;
                for (Object item : array) {
                    if (!isEmpty(recursion, item)) {
                        return false;
                    }
                }
            }
        } else if (obj instanceof Map map) {
            if (map.isEmpty()) {
                return true;
            }
            if (recursion) {
                for (Object item : map.values()) {
                    if (!isEmpty(recursion, item)) {
                        return false;
                    }
                }
            } else {
                return false;
            }
        } else {
            String tmp = obj.toString();
            if (null == tmp) {
                return true;
            }
            tmp = tmp.trim();
            return tmp.isEmpty() || tmp.equals("null");
        }
        return true;
    }

    public static Long parseLong(Object value) {
        if (value instanceof Long) {
            return (Long) value;
        }
        if (value instanceof Date date) {
            return date.getTime();
        }
        if (value instanceof LocalDateTime || value instanceof LocalDate) {
            return DateUtil.parse(value).getTime();
        }
        return Long.parseLong(value.toString());
    }

    public static Long parseLong(Object value, Long def) {
        try {
            return parseLong(value);
        } catch (Exception e) {
            return def;
        }
    }

    public static BigDecimal parseDecimal(Object value, BigDecimal def) {
        if (null == value) {
            return def;
        }
        if (value instanceof BigDecimal) {
            return (BigDecimal) value;
        }
        BigDecimal result;
        switch (value) {
            case Long l -> result = new BigDecimal(l);
            case Date date -> result = new BigDecimal(date.getTime());
            case LocalDateTime localDateTime -> result = new BigDecimal(DateUtil.parse(localDateTime).getTime());
            case LocalDate localDate -> result = new BigDecimal(DateUtil.parse(localDate).getTime());
            default -> {
                try {
                    result = new BigDecimal(value.toString());
                } catch (Exception e) {
                    return def;
                }
            }
        }
        return result;
    }

    public static boolean isEmpty(Object obj) {
        return isEmpty(false, obj);
    }


    public static boolean isNotEmpty(Object obj) {
        return !isEmpty(false, obj);
    }

    public static boolean isNotEmpty(boolean recursion, Object obj) {
        return !isEmpty(recursion, obj);
    }

    public static boolean equals(Object obj1, Object obj2) {
        if (null == obj1) {
            return null == obj2;
        } else {
            if (null == obj2) {
                return false;
            } else {
                return obj1.toString().equals(obj2.toString());
            }
        }
    }

    public static boolean equalsIgnoreCase(Object obj1, Object obj2) {
        if (null == obj1) {
            return null == obj2;
        } else {
            if (null == obj2) {
                return false;
            } else {
                return obj1.toString().equalsIgnoreCase(obj2.toString());
            }
        }
    }

    /**
     * nvl 取第一个不为null的值, 没有符合条件的 则返回null
     *
     * @param values values
     * @param <T>    T
     * @return T
     */
    public static <T> T nvl(T... values) {
        if (null == values) {
            return null;
        }
        for (T item : values) {
            if (null != item) {
                return item;
            }
        }
        return null;
    }


    /**
     * 反回第一个不为空(""|null|empty)的值 没有符合条件的 则返回NULL
     * 与nvl区别 : ""不符合evl条件 但符合nvl条件
     *
     * @param recursion recursion
     * @param values    values
     * @param <T>       T
     * @return Object
     */
    public static <T> T evl(boolean recursion, T... values) {
        if (null == values) {
            return null;
        }
        for (T item : values) {
            if (isNotEmpty(recursion, item)) {
                return item;
            }
        }
        return null;
    }

    public static <T> T evl(T... values) {
        return evl(false, values);
    }

    /**
     * 生成随机字符串
     *
     * @param length length
     * @param buffer buffer
     * @return String
     */
    public static String getRandomString(int length, StringBuffer buffer) {
        StringBuilder sb = new StringBuilder();
        Random r = new Random();
        int range = buffer.length();
        for (int i = 0; i < length; i++) {
            sb.append(buffer.charAt(r.nextInt(range)));
        }
        return sb.toString();
    }

    public static String getRandomString(int length) {
        return getRandomString(length, new StringBuffer("012356789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"));
    }

    public static String getRandomNumberString(int length) {
        return getRandomString(length, new StringBuffer("123567890"));
    }

    /**
     * 判断数字
     *
     * @param obj obj
     * @return boolean
     */
    public static boolean isNumber(Object obj) {
        boolean result = false;
        if (obj == null) {
            return false;
        }
        if (obj instanceof Number)
            return true;
        String str = obj.toString();
        try {
            Double.parseDouble(str);
            result = true;
        } catch (Exception ignored) {
        }
        return result;
    }

    public static Integer parseInt(Object value, Integer def) {
        if (null == value) {
            return def;
        }
        if (value instanceof Integer) {
            return (Integer) value;
        }
        try {
            return (int) Double.parseDouble(value.toString().trim());
        } catch (Exception e) {
            return def;
        }
    }


    public static Float parseFloat(Object value, Float def) {
        if (null == value) {
            return def;
        }
        if (value instanceof Float) {
            return (Float) value;
        }
        try {
            return Float.parseFloat(value.toString());
        } catch (Exception e) {
            return def;
        }
    }

    public static Double parseDouble(Object value, Double def) {
        if (null == value) {
            return def;
        }
        if (value instanceof Double) {
            return (Double) value;
        }
        try {
            return Double.parseDouble(value.toString());
        } catch (Exception e) {
            return def;
        }
    }

    /**
     * 类型转换
     *
     * @param obj obj
     * @param def def
     * @return Boolean
     */
    public static Boolean parseBoolean(Object obj, Boolean def) {
        if (obj instanceof Boolean) {
            return (Boolean) obj;
        }
        try {
            return parseBoolean(obj);
        } catch (Exception e) {
            return def;
        }
    }

    public static Boolean parseBoolean(Object obj) {
        if (obj instanceof Boolean) {
            return (Boolean) obj;
        }
        if ("1".equals(obj.toString())
                || "true".equalsIgnoreCase(obj.toString())
                || "t".equalsIgnoreCase(obj.toString())
                || "on".equalsIgnoreCase(obj.toString())
                || "yes".equalsIgnoreCase(obj.toString())
                || "y".equalsIgnoreCase(obj.toString())) {
            return true;
        } else if ("0".equals(obj.toString())
                || "false".equalsIgnoreCase(obj.toString())
                || "off".equalsIgnoreCase(obj.toString())
                || "f".equalsIgnoreCase(obj.toString())
                || "no".equalsIgnoreCase(obj.toString())
                || "n".equalsIgnoreCase(obj.toString())) {
            return false;
        } else {
            return Boolean.parseBoolean(obj.toString());
        }
    }

    /**
     * 填充字符(从左侧填充)
     *
     * @param src 原文
     * @param chr 填充字符
     * @param len 需要达到的长度
     * @return String
     */
    public static String fillLChar(String src, String chr, int len) {
        if (null != src && null != chr && !chr.isEmpty()) {
            StringBuilder srcBuilder = new StringBuilder(src);
            while (srcBuilder.length() < len) {
                srcBuilder.insert(0, chr);
            }
            src = srcBuilder.toString();
        }
        return src;
    }


    public static <T> int index(boolean ignoreNull, boolean ignoreCase, Collection<T> objs, String obj) {
        int idx = -1;
        if (null == objs) {
            return -1;
        }
        for (T o : objs) {
            idx++;
            if (ignoreNull) {
                if (null == obj || null == o) {
                    continue;
                }
            } else {
                if (null == obj && null == o) {
                    return idx;
                }
            }
            if (null != obj) {
                if (null == o) {
                    continue;
                }
                String val = o.toString();
                if (ignoreCase) {
                    obj = obj.toLowerCase();
                    val = val.toLowerCase();
                }
                if (obj.equals(val)) {
                    return idx;
                }
            }
        }
        return -1;
    }

}
